// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space 
// Source File Name:   ConfigParser.java

package com.solab.iso8583.parse;

import com.solab.iso8583.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import javax.xml.parsers.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

// Referenced classes of package com.solab.iso8583.parse:
//			FieldParseInfo

public class ConfigParser
{

	private static final Log log = LogFactory.getLog(ConfigParser.class);

	public ConfigParser()
	{
	}

	public static MessageFactory createDefault()
		throws IOException
	{
		if (MessageFactory.class.getClassLoader().getResource("config.xml") == null)
		{
			log.warn("j8583.xml not found, returning empty message factory");
			return new MessageFactory();
		} else
		{
			return createFromClasspathConfig("j8583.xml");
		}
	}

	public static MessageFactory createFromClasspathConfig(String path)
		throws IOException
	{
		InputStream ins = MessageFactory.class.getClassLoader().getResourceAsStream(path);
	    MessageFactory mfact = new MessageFactory();
	    if (ins != null) {
	      if (log.isDebugEnabled())
	        log.debug("Parsing config from classpath file " + path);
	      try
	      {
	        parse(mfact, ins);
	      } finally {
	        ins.close();
	      }
	    } else {
	      log.warn("File not found in classpath: " + path);
	    }
	    return mfact;
	}

	public static MessageFactory createFromUrl(URL url)
		throws IOException
	{
		 MessageFactory mfact = new MessageFactory();
		    InputStream stream = url.openStream();
		    try {
		      parse(mfact, stream);
		    } finally {
		      stream.close();
		    }
		    return mfact;
	}

	protected static void parse(MessageFactory mfact, InputStream stream)
		throws IOException
	{
		DocumentBuilderFactory docfact = DocumentBuilderFactory.newInstance();
		DocumentBuilder docb = null;
		Document doc = null;
		try
		{
			docb = docfact.newDocumentBuilder();
			doc = docb.parse(stream);
		}
		catch (ParserConfigurationException ex)
		{
			log.error("Cannot parse XML configuration", ex);
			return;
		}
		catch (SAXException ex)
		{
			log.error("Parsing XML configuration", ex);
			return;
		}
		Element root = doc.getDocumentElement();
		NodeList nodes = root.getElementsByTagName("header");
		Element elem = null;
		for (int i = 0; i < nodes.getLength(); i++)
		{
			elem = (Element)nodes.item(i);
			int type = parseType(elem.getAttribute("type"));
			if (type == -1)
				throw new IOException((new StringBuilder("Invalid type for header: ")).append(elem.getAttribute("type")).toString());
			if (elem.getChildNodes() == null || elem.getChildNodes().getLength() == 0)
				throw new IOException("Invalid header element");
			String header = elem.getChildNodes().item(0).getNodeValue();
			if (log.isTraceEnabled())
				log.trace((new StringBuilder("Adding ISO header for type ")).append(elem.getAttribute("type")).append(": ").append(header).toString());
			mfact.setIsoHeader(type, header);
		}

		nodes = root.getElementsByTagName("template");
		for (int i = 0; i < nodes.getLength(); i++)
		{
			elem = (Element)nodes.item(i);
			int type = parseType(elem.getAttribute("type"));
			if (type == -1)
				throw new IOException((new StringBuilder("Invalid type for template: ")).append(elem.getAttribute("type")).toString());
			NodeList fields = elem.getElementsByTagName("field");
			IsoMessage m = new IsoMessage();
			m.setType(type);
			for (int j = 0; j < fields.getLength(); j++)
			{
				Element f = (Element)fields.item(j);
				int num = Integer.parseInt(f.getAttribute("num"));
				IsoType itype = IsoType.valueOf(f.getAttribute("type"));
				int length = 0;
				if (f.getAttribute("length").length() > 0)
					length = Integer.parseInt(f.getAttribute("length"));
				String v = f.getChildNodes().item(0).getNodeValue();
				m.setValue(num, v, itype, length);
			}

			mfact.addMessageTemplate(m);
		}

		nodes = root.getElementsByTagName("parse");
		for (int i = 0; i < nodes.getLength(); i++)
		{
			elem = (Element)nodes.item(i);
			int type = parseType(elem.getAttribute("type"));
			if (type == -1)
				throw new IOException((new StringBuilder("Invalid type for parse guide: ")).append(elem.getAttribute("type")).toString());
			NodeList fields = elem.getElementsByTagName("field");
			HashMap parseMap = new HashMap();
			for (int j = 0; j < fields.getLength(); j++)
			{
				Element f = (Element)fields.item(j);
				Integer num = new Integer(f.getAttribute("num"));
				IsoType itype = IsoType.valueOf(f.getAttribute("type"));
				int length = 0;
				if (f.getAttribute("length").length() > 0)
					length = Integer.parseInt(f.getAttribute("length"));
				parseMap.put(num, new FieldParseInfo(itype, length));
			}

			mfact.setParseMap(new Integer(type), parseMap);
		}

	}

	private static int parseType(String type)
		throws IOException
	{
		if (type.length() % 2 == 1)
			type = (new StringBuilder("0")).append(type).toString();
		if (type.length() != 4)
			return -1;
		else
			return type.charAt(0) - 48 << 12 | type.charAt(1) - 48 << 8 | type.charAt(2) - 48 << 4 | type.charAt(3) - 48;
	}

}
